gtk/window: Only fake motion events on windows with pending allocations
authorJonas Ådahl <jadahl@gmail.com>
Thu, 3 Dec 2020 21:50:31 +0000 (22:50 +0100)
committerJonas Ådahl <jadahl@gmail.com>
Mon, 7 Dec 2020 19:37:29 +0000 (20:37 +0100)
This fixes an issue where the focus of the window continuously received
fake motion events even when a popover was open, making input events end
up behind the popover.

It also adds a comment describing why motion events are requested. Note
that popovers won't work with this, and it's possible both in the past
and now that sporadic missplaced motion events will appear, e.g. when a
window changes allocation but a popover is open.

gtk/gtkwindow.c

index 2ffc166894be659645ed334e4d0ef84c47492f4d..07c23b0761da8664ec2c3894e65b67753783a8ec 100644 (file)
@@ -1894,7 +1894,6 @@ gtk_window_native_layout (GtkNative *native,
   GtkWindow *window = GTK_WINDOW (native);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
   GtkWidget *widget = GTK_WIDGET (native);
-  GdkSeat *seat;
 
   if (priv->surface_width != width || priv->surface_height != height)
     {
@@ -1903,21 +1902,30 @@ gtk_window_native_layout (GtkNative *native,
       priv->surface_height = height;
     }
 
-  seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
-  if (seat)
+  /* This fake motion event is needed for getting up to date pointer focus
+   * and coordinates when tho pointer didn't move but the layout changed
+   * within the window.
+   */
+  if (gtk_widget_needs_allocate (widget))
     {
-      GdkDevice *device;
-      GtkWidget *focus;
+      GdkSeat *seat;
 
-      device = gdk_seat_get_pointer (seat);
-      focus = gtk_window_lookup_pointer_focus_widget (GTK_WINDOW (widget),
-                                                      device, NULL);
-      if (focus)
+      seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
+      if (seat)
         {
-          GdkSurface *focus_surface =
-            gtk_native_get_surface (gtk_widget_get_native (focus));
+          GdkDevice *device;
+          GtkWidget *focus;
+
+          device = gdk_seat_get_pointer (seat);
+          focus = gtk_window_lookup_pointer_focus_widget (GTK_WINDOW (widget),
+                                                          device, NULL);
+          if (focus)
+            {
+              GdkSurface *focus_surface =
+                gtk_native_get_surface (gtk_widget_get_native (focus));
 
-          gdk_surface_request_motion (focus_surface);
+              gdk_surface_request_motion (focus_surface);
+            }
         }
     }